<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>upload</title>
  <style>
    #whole {
      width: 400px;
      height: 400px;
      text-align: center;
      margin: 0 auto;
    }

    .btn {
      position: relative;
      width: 60px;
      height: 30px;
      line-height: 30px;
      margin-left: 60px;
      bottom: 10px;
    }

    .li {
      height: 80px;
      line-height: 80px;
      list-style: none;
    }

    #box {
      margin-top: 50px;
    }
  </style>
</head>

<body>
  <div id="whole">
    <h2>生成验证码</h2>
    <div id="check">
      <canvas id="cas" width="150" height="60" onclick="verifity()"></canvas>
      <input type="submit" value="提交" id="inp" />
    </div>
    <div id="box">
      <ul id="list"></ul>
    </div>
  </div>
</body>
<script>
  var cas = document.getElementById("cas"); //获取页面中的画布
  var ctx = cas.getContext("2d"); //获取2d画笔
  var inp = document.getElementById('inp');//获取提交按钮
  var whole = document.getElementById('whole');
  var box = document.getElementById('box');//获取列表盒子
  var list = document.getElementById('list');//获取列表

  // 将图片base64转换为File
  function dataURLtoFile(dataurl, filename) {
    var xarr = dataurl.split(',');
    var mime = xarr[0].match(/:(.*?);/)[1];
    var bstr = atob(xarr[1]);
    var n = bstr.length;
    var u8arr = new Uint8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n)
    }
    return new File([u8arr], filename, { type: mime })
  }

  //1. 产生随机数的函数
  function rn(min, max) {
    return Math.floor(Math.random() * (max - min) + min);
  }

  //2. 产生随机色的函数
  function rc(min, max) {
    let r = rn(min, max);
    let g = rn(min, max);
    let b = rn(min, max);
    return `rgb(${r},${g},${b})`;
  }

  let str = ""; //保存产生的4个随机字符
  verifity(); //调用函数保证渲染
  listCode();//获取数据

  var arr = [];
  var brr = [];

  // 点击删除按钮动态删除验证码图片
  function btnDelete(btn, name) {
    // console.log(name)
    btn.onclick = function () {
      list.innerHTML = null;
      fetch(`/image/${name}`, {
        method: 'delete',
      }).then(res => res.json())
        .then(res => {
          console.log(res)
          for (let i = 0; i < res.length; i++) {
            var btn = document.createElement('button');
            btn.setAttribute('class', 'btn')
            btn.innerHTML = '删除';
            var li = document.createElement('li');
            li.setAttribute('class', 'li')
            var img = document.createElement('img');
            var src = `/image/${res[i]}`;
            img.src = src;
            li.appendChild(img)
            li.appendChild(btn)
            list.appendChild(li)

            btnDelete(btn, res[i])
          }
        })
    }
  }

  // 首先获取后端传来的一批验证码的数据
  function listCode() {
    fetch('/image', {
      method: 'get',
    }).then(res => res.json())
      .then((res) => {
        console.log(res)
        // 动态添加节点显示验证码图片，并进行管理删除
        for (let i = 0; i < res.length; i++) {
          var btn = document.createElement('button');
          btn.setAttribute('class', 'btn')
          btn.innerHTML = '删除';
          var li = document.createElement('li');
          li.setAttribute('class', 'li')
          var img = document.createElement('img');
          var src = `/image/${res[i]}`;
          img.src = src;
          li.appendChild(img)
          li.appendChild(btn)
          list.appendChild(li)

          btnDelete(btn, res[i])
          // console.log(res[i])

        }
      })

  }


  // 提交一批验证码，并展示
  inp.onclick = function () {
    for (var n = 0; n < 6; n++) {
      const obj = {};
      verifity(); //调用函数保证渲染
      let src = cas.toDataURL();
      obj.name = '图片' + new Date().getTime();
      obj.answer = str;
      obj.src = src;
      arr.push(obj);
    }
    // console.log(arr)
    for (var i = 0; i < arr.length; i++) {
      var file = dataURLtoFile(arr[i].src, arr[i].name)
      file.answer = arr[i].answer
      brr.unshift(file)
    }
    console.log(brr)
    arr = [];

    // 提交生成的验证码图片
    const formData = new FormData();
    for (var j = 0; j < 6; j++) {
      formData.append('image', brr[j])
      formData.append('answer', brr[j].answer)
      console.log(brr[j])
    }
    fetch('/image', {
      method: 'post',
      body: formData,
    })
      .then(res => {
        // 获取上传的一批验证码的数据
        listCode();
      })

  }


  // 产生随机字符串
  function verifity() {
    const pool = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
    //3.填充颜色,颜色需浅
    const w = 150;
    const h = 60;
    ctx.fillStyle = rc(150, 220);
    ctx.fillRect(0, 0, w, h);

    //4. 绘制文字
    str = ""; //清空str的上一次的内容
    for (let i = 0; i < 4; i++) {
      let s = pool[rn(0, pool.length)]; //随机的字符
      let fs = rn(20, 30); //字体大小
      let deg = rn(-30, 30);
      // ctx.translate(8, 5);
      ctx.font = fs + "px Simhei"; //字体的样式
      ctx.textBaseline = "top"; //绘制文本的基线:以上边线为界
      ctx.fillStyle = rc(150, 60); //设置填充颜色
      ctx.save(); //保存前面对画笔的设置

      ctx.translate(30 * i + 15, 15); //平移坐标系
      ctx.rotate((deg * Math.PI) / 200); //设置文本的偏转角度
      ctx.fillText(s, -2 + 5, -2); //绘制文本
      ctx.restore(); //清除前面画笔的设置,画笔恢复初始装态
      str += s;
    }
    //5. 随机产生8条干扰线,颜色需浅
    for (let i = 0; i < 8; i++) {
      ctx.beginPath(); //重置路径
      ctx.moveTo(rn(0, w), rn(0, h)); //设置线条起点
      ctx.lineTo(rn(0, w), rn(0, h));
      ctx.closePath(); //关闭路径
      ctx.strokeStyle = rc(150, 200);
      ctx.stroke();
    }

    //6. 随机产生40个干扰小圆点
    for (let i = 0; i < 40; i++) {
      ctx.beginPath();
      ctx.arc(rn(0, w), rn(0, h), 1, 0, 2 * Math.PI);
      ctx.closePath();
      ctx.fillStyle = rc(150, 200);
      ctx.fill();
    }
  }

</script>

</html>